/*
Copyright (C) 2022-2024 Inspur Corp. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/
package base58

import (
	"bytes"
	"math/big"
)

var B58Alph = []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")

func Encode(input string) string {
	var result []byte
	x := big.NewInt(0).SetBytes([]byte(input))
	base := big.NewInt(int64(len(B58Alph)))
	zero := big.NewInt(0)
	mod := &big.Int{}
	for x.Cmp(zero) != 0 {
		x.DivMod(x, base, mod)
		result = append(result, B58Alph[mod.Int64()])
	}
	ReverseBytes(result)
	for _, b := range []byte(input) {
		if b == 0x00 {
			result = append([]byte{B58Alph[0]}, result...)
		} else {
			break
		}
	}
	return string(result)
}

func Decode(data string) string {
	input := []byte(data)
	result := big.NewInt(0)
	zeroBytes := 0
	for _, b := range input {
		if b == '1' {
			zeroBytes++
		} else {
			break
		}
	}
	payload := input[zeroBytes:]
	for _, b := range payload {
		charIndex := bytes.IndexByte(B58Alph, b)
		result.Mul(result, big.NewInt(58))
		result.Add(result, big.NewInt(int64(charIndex)))
	}
	decoded := result.Bytes()
	decoded = append(bytes.Repeat([]byte{0x00}, zeroBytes), decoded...)
	return string(decoded)
}

func ReverseBytes(data []byte) {
	for i, j := 0, len(data)-1; i < j; i, j = i+1, j-1 {
		data[i], data[j] = data[j], data[i]
	}
}
